#ifndef OBJECT_HPP
#define OBJECT_HPP

#include "Common.hpp"

#include <list>
#include <stack>

class Model;
class Iterator;

class Object
{
public:
  
  Object(Object * parent = 0,
         const glm::mat4 & modelMatrix = glm::mat4(1.0f),
         Model * model = 0,
         
         const std::string & name = "_untitled"
        );
  virtual ~Object();
  
  virtual void update();
  virtual void draw(const glm::mat4 & modelMatrix);
  
  Object * lowestCommonAncestor(Object * other);
  
  void setModelMatrix(const glm::mat4 & modelMatrix);
  glm::mat4 getModelMatrix() const {return m_modelMatrix; }
  glm::mat4 getWorldModelMatrix() const;
  void transform(const glm::mat4 & transform);

  void attachChild(Object * obj);
  void detachChild(Object * obj);
  
  Iterator begin();
  Iterator end();
  
  Model * m_model;
  
  Object * m_parent;
  glm::mat4 m_modelMatrix;
    GLint m_ul_model;
  
  std::string getName() {return m_name; }
    std::string m_name;
  
protected:
 
  
private:


  
  std::list<Object*> m_children;
  
  friend class Iterator;
};

class Iterator
{
private:
  Iterator(Object * obj = 0)
    : m_obj(obj)
  {
  }
  
public:  
  Object* operator*()
  {
    return m_obj;
  }
  
  bool operator==(const Iterator& rhs)
  {
    return m_obj == rhs.m_obj;
  }
  
  bool operator!=(const Iterator& rhs)
  {
    return m_obj != rhs.m_obj;
  }
  
  Iterator& operator++();
  
private:
  Object * m_obj;
  Object * m_parent;
  std::list<Object*>::iterator m_itr;
  std::stack<std::list<Object*>::iterator> m_itrs;
  friend class Object;
};

#endif // OBJECT_HPP
